]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
popupMenu: Only connect to notify::key-focus when needed
authorSebastian Keller <skeller@gnome.org>
Mon, 30 Oct 2023 10:18:25 +0000 (11:18 +0100)
committerMarge Bot <marge-bot@gnome.org>
Fri, 3 Nov 2023 20:33:23 +0000 (20:33 +0000)
PopupMenuManager was connecting to notify::key-focus on the stage on
construction, but only ever reacting to it when one of its menus was
open. Given that every single app icon and text entry creates a
PopupMenuManager this was causing a lot of these handlers to be created.
Every single handler meant calling into JS code only for the vast
majority of them to determine that they would not do anything.

Additionally these handlers were leaked for the whole lifetime of the
stage due to never getting disconnected.

This now only connects the handler when a menu is open and disconnects
again when it is closed, significantly reducing the number of active
handlers at a time.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7143
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3001>

js/ui/popupMenu.js

index b2a3c4a481dce11994258f34e041ed7b27f6a0d8..f06bee65fcd10912c9d0f78da9048f4c5c6f9f2f 100644 (file)
@@ -1276,16 +1276,6 @@ export class PopupMenuManager {
     constructor(owner, grabParams) {
         this._grabParams = Params.parse(grabParams,
             {actionMode: Shell.ActionMode.POPUP});
-        global.stage.connect('notify::key-focus', () => {
-            if (!this.activeMenu)
-                return;
-
-            let actor = global.stage.get_key_focus();
-            let newMenu = this._findMenuForSource(actor);
-
-            if (newMenu)
-                this._changeMenu(newMenu);
-        });
         this._menus = [];
     }
 
@@ -1309,6 +1299,11 @@ export class PopupMenuManager {
         if (menu === this.activeMenu) {
             Main.popModal(this._grab);
             this._grab = null;
+
+            if (this._keyFocusId) {
+                global.stage.disconnect(this._keyFocusId);
+                delete this._keyFocusId;
+            }
         }
 
         const position = this._menus.indexOf(menu);
@@ -1336,10 +1331,29 @@ export class PopupMenuManager {
             oldMenu?.close(BoxPointer.PopupAnimation.FADE);
             if (oldGrab)
                 Main.popModal(oldGrab);
+
+            if (!this._keyFocusId) {
+                this._keyFocusId =
+                    global.stage.connect('notify::key-focus', () => {
+                        if (!this.activeMenu)
+                            return;
+
+                        let actor = global.stage.get_key_focus();
+                        let newMenu = this._findMenuForSource(actor);
+
+                        if (newMenu)
+                            this._changeMenu(newMenu);
+                    });
+            }
         } else if (this.activeMenu === menu) {
             this.activeMenu = null;
             Main.popModal(this._grab);
             this._grab = null;
+
+            if (this._keyFocusId) {
+                global.stage.disconnect(this._keyFocusId);
+                delete this._keyFocusId;
+            }
         }
     }